package com.yanqu.xiuxian.crosssystem.manger.elementalbonds.logic;

import com.yanqu.xiuxian.config.elementalbonds.ElementalBondsParam;
import com.yanqu.xiuxian.config.elementalbonds.enums.*;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.data.ElementalBondsGameData;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.ElementalBondsBlock;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.ElementalBondsBlockEffect;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.ElementalBondsBomb;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.param.ElementalBondsMoveParam;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.result.*;

import java.util.*;

public class ElementalBondsBombLogic {

    public static void fastBoom(ElementalBondsGameData elementalBondsGameData,
                                ElementalBondsOperateType elementalBondsOperateType, Set<ElementalBondsBlock> elementalBondsBlockSet, List<ElementalBondsBomb> elementalBondsBombList) {
        // 检查下边框消除
        ElementalBondsEliminateLogic.eliminateFrame(elementalBondsGameData, elementalBondsBlockSet, elementalBondsOperateType);

        // 找未爆炸的炸弹
        Set<ElementalBondsBlock> canBoomBlockSet = ElementalBondsBlockLogic.getCanBoomBlock(elementalBondsBombList, elementalBondsBlockSet);

        // 马上爆炸
        handleBombBoom(elementalBondsGameData.getBlockList(), canBoomBlockSet, elementalBondsBlockSet, elementalBondsBombList);
    }

    public static void handleBombBoom(List<List<ElementalBondsBlock>> blockList, Set<ElementalBondsBlock> handleBlockSet,
                                      Set<ElementalBondsBlock> roundEliminateSet, List<ElementalBondsBomb> elementalBondsBombList) {
        for (ElementalBondsBlock elementalBondsBlock : handleBlockSet) {
            List<ElementalBondsBombType> bombTypeList = getBombTypeList(elementalBondsBlock);
            for (ElementalBondsBombType elementalBondsBombType : bombTypeList) {
                // 炸弹效果
                ElementalBondsBomb elementalBondsBomb = new ElementalBondsBomb(elementalBondsBlock.getX(), elementalBondsBlock.getY(),
                        elementalBondsBombType, elementalBondsBlock.getElementalBondsDirectionType());
                Set<ElementalBondsBlock> boomAreaElementalBondsBlockSet = getBoomArea(blockList, elementalBondsBomb, roundEliminateSet);
                elementalBondsBomb.setElementalBondsBlockList(new ArrayList<>(boomAreaElementalBondsBlockSet));
                // 添加爆炸效果
                elementalBondsBombList.add(elementalBondsBomb);
                // 添加消除格子
                roundEliminateSet.addAll(elementalBondsBomb.getElementalBondsBlockList());
            }
        }
    }

    public static List<ElementalBondsBombType> getBombTypeList(ElementalBondsBlock elementalBondsBlock) {
        List<ElementalBondsBombType> bombTypeList = new ArrayList<>();
        ElementalBondsBlockType elementalBondsBlockType = elementalBondsBlock.getElementalBondsBlockType();
        if (elementalBondsBlockType == ElementalBondsBlockType.LINE_BOMB) {
            bombTypeList.add(ElementalBondsBombType.LINE);
        } else if (elementalBondsBlockType == ElementalBondsBlockType.COLUMN_BOMB) {
            bombTypeList.add(ElementalBondsBombType.COLUMN);
        } else if (elementalBondsBlockType == ElementalBondsBlockType.LANDMINE || elementalBondsBlockType == ElementalBondsBlockType.SMART_BOX_LANDMINE
                || elementalBondsBlockType == ElementalBondsBlockType.HUO_YAO_KUANG_HUAN) {
            bombTypeList.add(ElementalBondsBombType.LOZENGE);
        } else if (elementalBondsBlockType == ElementalBondsBlockType.METEOR || elementalBondsBlockType == ElementalBondsBlockType.METEOR_BOMB) {
            bombTypeList.add(ElementalBondsBombType.METEOR);
        } else if (elementalBondsBlockType == ElementalBondsBlockType.GUI_KE_ZHAN_BU) {
            bombTypeList.add(ElementalBondsBombType.GUI_KE_ZHAN_BU);
        } else if (elementalBondsBlockType == ElementalBondsBlockType.ROCKET || elementalBondsBlockType == ElementalBondsBlockType.YAN_HUO_KUANG_HUAN) {
            bombTypeList.add(ElementalBondsBombType.ROCKET);
        } else if (elementalBondsBlockType == ElementalBondsBlockType.PAPER_FLOWER) {
            bombTypeList.add(ElementalBondsBombType.PAPER_FLOWER_SAME_COLOR);
        } else if (elementalBondsBlockType == ElementalBondsBlockType.DUN_HUANG_FEI_TIAN) {
            bombTypeList.add(ElementalBondsBombType.DUN_HUANG_FEI_TIAN);
        }

        for (ElementalBondsBlockEffect elementalBondsBlockEffect : elementalBondsBlock.getElementalBondsBlockEffectList()) {
            if (elementalBondsBlockEffect.getEffectType() == ElementalBondsBlockEffectType.SKILL_22) {
                int effectValue = elementalBondsBlockEffect.getEffectValue();
                if (effectValue == 1) {
                    bombTypeList.add(ElementalBondsBombType.LITTLE_DEVILS_COLUMN);
                } else if (effectValue == 2) {
                    bombTypeList.add(ElementalBondsBombType.LITTLE_DEVILS_LINE);
                } else if (effectValue == 3) {
                    bombTypeList.add(ElementalBondsBombType.LITTLE_DEVILS_CROSS);
                }
            }
        }
        return bombTypeList;
    }

    public static Set<ElementalBondsBlock> getBoomArea(List<List<ElementalBondsBlock>> blockList,
                                                       ElementalBondsBomb elementalBondsBomb, Set<ElementalBondsBlock> elementalBondsBlockSet) {

        Set<ElementalBondsBlock> boomAreaElementalBondsBlockSet = new HashSet<>();

        ElementalBondsBombType elementalBondsBombType = elementalBondsBomb.getElementalBondsBombType();
        int x = elementalBondsBomb.getX();
        int y = elementalBondsBomb.getY();

        if (elementalBondsBombType == ElementalBondsBombType.LINE) {
            // 单行
            boomAreaElementalBondsBlockSet.addAll(blockList.get(y));
        } else if (elementalBondsBombType == ElementalBondsBombType.COLUMN) {
            // 单列
            for (int tmpY = 0; tmpY < blockList.size(); tmpY++) {
                boomAreaElementalBondsBlockSet.add(blockList.get(tmpY).get(x));
            }
        } else if (elementalBondsBombType == ElementalBondsBombType.LOZENGE) {
            // 地雷
            if (ElementalBondsBlockLogic.exist(blockList, x, y + 2))
                boomAreaElementalBondsBlockSet.add(blockList.get(y + 2).get(x));

            if (ElementalBondsBlockLogic.exist(blockList, x - 1, y + 1))
                boomAreaElementalBondsBlockSet.add(blockList.get(y + 1).get(x - 1));
            if (ElementalBondsBlockLogic.exist(blockList, x, y + 1))
                boomAreaElementalBondsBlockSet.add(blockList.get(y + 1).get(x));
            if (ElementalBondsBlockLogic.exist(blockList, x + 1, y + 1))
                boomAreaElementalBondsBlockSet.add(blockList.get(y + 1).get(x + 1));

            if (ElementalBondsBlockLogic.exist(blockList, x - 2, y))
                boomAreaElementalBondsBlockSet.add(blockList.get(y).get(x - 2));
            if (ElementalBondsBlockLogic.exist(blockList, x - 1, y))
                boomAreaElementalBondsBlockSet.add(blockList.get(y).get(x - 1));
            if (ElementalBondsBlockLogic.exist(blockList, x + 1, y))
                boomAreaElementalBondsBlockSet.add(blockList.get(y).get(x + 1));
            if (ElementalBondsBlockLogic.exist(blockList, x + 2, y))
                boomAreaElementalBondsBlockSet.add(blockList.get(y).get(x + 2));

            if (ElementalBondsBlockLogic.exist(blockList, x - 1, y - 1))
                boomAreaElementalBondsBlockSet.add(blockList.get(y - 1).get(x - 1));
            if (ElementalBondsBlockLogic.exist(blockList, x, y - 1))
                boomAreaElementalBondsBlockSet.add(blockList.get(y - 1).get(x));
            if (ElementalBondsBlockLogic.exist(blockList, x + 1, y - 1))
                boomAreaElementalBondsBlockSet.add(blockList.get(y - 1).get(x + 1));

            if (ElementalBondsBlockLogic.exist(blockList, x, y - 2))
                boomAreaElementalBondsBlockSet.add(blockList.get(y - 2).get(x));
        } else if (elementalBondsBombType == ElementalBondsBombType.METEOR) {
            // 流星
            List<ElementalBondsBlock> elementalBondsBlockList = new ArrayList<>();
            for (List<ElementalBondsBlock> elementalBondsBlocks : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlocks) {
                    if (!elementalBondsBlockSet.contains(elementalBondsBlock)) {
                        elementalBondsBlockList.add(elementalBondsBlock);
                    }
                }
            }
            Collections.shuffle(elementalBondsBlockList);
            int maxIndex = ElementalBondsParam.getInstance().getMeteorEliminateNum();
            for (int i = 0; i < maxIndex && i < elementalBondsBlockList.size(); i++) {
                ElementalBondsBlock elementalBondsBlock = elementalBondsBlockList.get(i);
                if (elementalBondsBlock.getX() == x && elementalBondsBlock.getY() == y) {
                    maxIndex++; // 跳过自己
                } else {
                    boomAreaElementalBondsBlockSet.add(elementalBondsBlock);
                }
            }
        } else if (elementalBondsBombType == ElementalBondsBombType.GUI_KE_ZHAN_BU) {
            // 龟壳占卜
            List<ElementalBondsBlock> elementalBondsBlockList = new ArrayList<>();
            for (List<ElementalBondsBlock> elementalBondsBlocks : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlocks) {
                    if (elementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.NORMAL
                            && !elementalBondsBlockSet.contains(elementalBondsBlock)) {
                        elementalBondsBlockList.add(elementalBondsBlock);
                    }
                }
            }
            Collections.shuffle(elementalBondsBlockList);
            int eliminateNum = ElementalBondsSceneLogic.scene_06_getEliminateNum();
            for (int i = 0; i < eliminateNum && i < elementalBondsBlockList.size(); i++) {
                ElementalBondsBlock elementalBondsBlock = elementalBondsBlockList.get(i);
                if (elementalBondsBlock.getX() == x && elementalBondsBlock.getY() == y) {
                    eliminateNum++; // 跳过自己
                } else {
                    boomAreaElementalBondsBlockSet.add(elementalBondsBlock);
                }
            }
        } else if (elementalBondsBombType == ElementalBondsBombType.ROCKET) {
            // 火箭
            ElementalBondsDirectionType elementalBondsDirectionType = elementalBondsBomb.getElementalBondsDirectionType();
            if (elementalBondsDirectionType == ElementalBondsDirectionType.UP) {
                for (int tmpY = y + 1; tmpY < blockList.size(); tmpY++) {
                    boomAreaElementalBondsBlockSet.add(blockList.get(tmpY).get(x));
                }
            } else if (elementalBondsDirectionType == ElementalBondsDirectionType.DOWN) {
                for (int tmpY = y - 1; tmpY >= 0; tmpY--) {
                    boomAreaElementalBondsBlockSet.add(blockList.get(tmpY).get(x));
                }
            } else if (elementalBondsDirectionType == ElementalBondsDirectionType.LEFT) {
                for (int tmpX = 0; tmpX < x; tmpX++) {
                    boomAreaElementalBondsBlockSet.add(blockList.get(y).get(tmpX));
                }
            } else if (elementalBondsDirectionType == ElementalBondsDirectionType.RIGHT) {
                for (int tmpX = x + 1; tmpX < blockList.get(y).size(); tmpX++) {
                    boomAreaElementalBondsBlockSet.add(blockList.get(y).get(tmpX));
                }
            }
        } else if (elementalBondsBombType == ElementalBondsBombType.PAPER_FLOWER_SAME_COLOR) {
            // 小窗花消除同色
            ElementalBondsBlock baseElementalBondsBlock = blockList.get(elementalBondsBomb.getY()).get(elementalBondsBomb.getX());
            for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                    if (elementalBondsBlock.getColor() == baseElementalBondsBlock.getColor()) {
                        boomAreaElementalBondsBlockSet.add(elementalBondsBlock);
                    }
                }
            }
        } else if (elementalBondsBombType == ElementalBondsBombType.LITTLE_DEVILS_COLUMN) {
            // 小恶魔Y
            for (int tmpY = 0; tmpY < elementalBondsBomb.getY(); tmpY++) {
                boomAreaElementalBondsBlockSet.add(blockList.get(tmpY).get(elementalBondsBomb.getX()));
            }
            int addi = 0;
            while (true) {
                addi++;
                if (ElementalBondsBlockLogic.exist(blockList, elementalBondsBomb.getX() + addi, elementalBondsBomb.getY() + addi)) {
                    boomAreaElementalBondsBlockSet.add(blockList.get(elementalBondsBomb.getY() + addi).get(elementalBondsBomb.getX() + addi));
                } else {
                    break;
                }
            }
            addi = 0;
            while (true) {
                addi++;
                if (ElementalBondsBlockLogic.exist(blockList, elementalBondsBomb.getX() - addi, elementalBondsBomb.getY() + addi)) {
                    boomAreaElementalBondsBlockSet.add(blockList.get(elementalBondsBomb.getY() + addi).get(elementalBondsBomb.getX() - addi));
                } else {
                    break;
                }
            }
        } else if (elementalBondsBombType == ElementalBondsBombType.LITTLE_DEVILS_LINE) {
            // 小恶魔X
            for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                    int subY = elementalBondsBlock.getY() - elementalBondsBomb.getY();
                    int subX = elementalBondsBlock.getX() - elementalBondsBomb.getX();
                    if (subY == 0 || subX == 0) {
                        continue;
                    }
                    if (Math.abs(subX) == Math.abs(subY)) {
                        boomAreaElementalBondsBlockSet.add(elementalBondsBlock);
                    }
                }
            }
        } else if (elementalBondsBombType == ElementalBondsBombType.LITTLE_DEVILS_CROSS) {
            // 小恶魔十字
            boomAreaElementalBondsBlockSet.addAll(blockList.get(elementalBondsBomb.getY()));
            for (int tmpY = 0; tmpY < blockList.size(); tmpY++) {
                ElementalBondsBlock elementalBondsBlock = blockList.get(tmpY).get(elementalBondsBomb.getX());
                boomAreaElementalBondsBlockSet.add(elementalBondsBlock);
            }
        } else if (elementalBondsBombType == ElementalBondsBombType.DUN_HUANG_FEI_TIAN) {
            // 敦煌飞天
            for (int tmpY = y - 2; tmpY <= y + 2; tmpY++) {
                if (ElementalBondsBlockLogic.exist(blockList, x, tmpY)) {
                    boomAreaElementalBondsBlockSet.add(blockList.get(tmpY).get(x));
                }
            }
            for (int tmpX = x - 2; tmpX <= x + 2; tmpX++) {
                if (ElementalBondsBlockLogic.exist(blockList, tmpX, y)) {
                    boomAreaElementalBondsBlockSet.add(blockList.get(y).get(tmpX));
                }
            }
        }

        ElementalBondsBlockLogic.removeNoBaseFourBigType(boomAreaElementalBondsBlockSet);
        return boomAreaElementalBondsBlockSet;
    }

    public static void handleCombBombBoom(List<List<ElementalBondsBlock>> blockList, ElementalBondsMoveParam elementalBondsMoveParam,
                                          Set<ElementalBondsBlock> elementalBondsBlockSet, List<ElementalBondsBomb> elementalBondsBombList) {
        if (elementalBondsMoveParam == null) {
            return;
        }

        ElementalBondsBlock fromElementalBondsBlock = blockList.get(elementalBondsMoveParam.getFromY()).get(elementalBondsMoveParam.getFromX());
        ElementalBondsBlock toElementalBondsBlock = blockList.get(elementalBondsMoveParam.getToY()).get(elementalBondsMoveParam.getToX());
        List<ElementalBondsBomb> bombList = new ArrayList<>();

        // 获取单独爆炸效果，其中可能包含effect的爆炸效果
        List<ElementalBondsBombType> fromBombTypeList = getBombTypeList(fromElementalBondsBlock);
        List<ElementalBondsBombType> toBombTypeList = getBombTypeList(toElementalBondsBlock);

        if ((fromElementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.LINE_BOMB || fromElementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.COLUMN_BOMB)
                && (toElementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.LINE_BOMB || toElementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.COLUMN_BOMB)) {
            // 行/列+行/列 => 十字
            bombList.add(new ElementalBondsBomb(toElementalBondsBlock.getX(), toElementalBondsBlock.getY(), ElementalBondsBombType.LINE, toElementalBondsBlock.getElementalBondsDirectionType()));
            bombList.add(new ElementalBondsBomb(toElementalBondsBlock.getX(), toElementalBondsBlock.getY(), ElementalBondsBombType.COLUMN, toElementalBondsBlock.getElementalBondsDirectionType()));
            bombList.add(new ElementalBondsBomb(fromElementalBondsBlock.getX(), fromElementalBondsBlock.getY(), ElementalBondsBombType.EMPTY, toElementalBondsBlock.getElementalBondsDirectionType()));
            fromBombTypeList.removeIf(elementalBondsBombType -> elementalBondsBombType == ElementalBondsBombType.LINE || elementalBondsBombType == ElementalBondsBombType.COLUMN);
            toBombTypeList.removeIf(elementalBondsBombType -> elementalBondsBombType == ElementalBondsBombType.LINE || elementalBondsBombType == ElementalBondsBombType.COLUMN);
            for (ElementalBondsBombType elementalBondsBombType : fromBombTypeList) {
                bombList.add(new ElementalBondsBomb(toElementalBondsBlock.getX(), toElementalBondsBlock.getY(), elementalBondsBombType, fromElementalBondsBlock.getElementalBondsDirectionType()));
            }
            for (ElementalBondsBombType elementalBondsBombType : toBombTypeList) {
                bombList.add(new ElementalBondsBomb(toElementalBondsBlock.getX(), toElementalBondsBlock.getY(), elementalBondsBombType, toElementalBondsBlock.getElementalBondsDirectionType()));
            }
        } else if ((fromElementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.LANDMINE && toElementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.LANDMINE)
                || (fromElementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.HUO_YAO_KUANG_HUAN && toElementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.HUO_YAO_KUANG_HUAN)) {
            // 炸弹+炸弹
            for (ElementalBondsBombType elementalBondsBombType : fromBombTypeList) {
                bombList.add(new ElementalBondsBomb(fromElementalBondsBlock.getX(), fromElementalBondsBlock.getY(), elementalBondsBombType, fromElementalBondsBlock.getElementalBondsDirectionType()));
            }
            for (ElementalBondsBombType elementalBondsBombType : toBombTypeList) {
                bombList.add(new ElementalBondsBomb(toElementalBondsBlock.getX(), toElementalBondsBlock.getY(), elementalBondsBombType, toElementalBondsBlock.getElementalBondsDirectionType()));
            }
        } else {
            // 其余的组合单独爆炸
            if (!ElementalBondsBlockLogic.combBombPart(fromElementalBondsBlock) || !ElementalBondsBlockLogic.combBombPart(toElementalBondsBlock)) {
                return; // 不是组合
            }
            for (ElementalBondsBombType elementalBondsBombType : fromBombTypeList) {
                bombList.add(new ElementalBondsBomb(toElementalBondsBlock.getX(), toElementalBondsBlock.getY(), elementalBondsBombType, fromElementalBondsBlock.getElementalBondsDirectionType()));
            }
            for (ElementalBondsBombType elementalBondsBombType : toBombTypeList) {
                bombList.add(new ElementalBondsBomb(toElementalBondsBlock.getX(), toElementalBondsBlock.getY(), elementalBondsBombType, toElementalBondsBlock.getElementalBondsDirectionType()));
            }
            bombList.add(new ElementalBondsBomb(fromElementalBondsBlock.getX(), fromElementalBondsBlock.getY(), ElementalBondsBombType.EMPTY, fromElementalBondsBlock.getElementalBondsDirectionType()));
        }

        // 添加消除的格子
        elementalBondsBlockSet.add(fromElementalBondsBlock);
        elementalBondsBlockSet.add(toElementalBondsBlock);

        // 添加爆炸信息
        for (ElementalBondsBomb elementalBondsBomb : bombList) {
            Set<ElementalBondsBlock> boomAreaElementalBondsBlockSet = getBoomArea(blockList, elementalBondsBomb, elementalBondsBlockSet);
            elementalBondsBomb.setElementalBondsBlockList(new ArrayList<>(boomAreaElementalBondsBlockSet));
            elementalBondsBlockSet.addAll(elementalBondsBomb.getElementalBondsBlockList());

            // 添加消除的格子
            elementalBondsBombList.add(elementalBondsBomb);
        }
    }

    public static List<ElementalBondsBlock> createBomb(ElementalBondsMoveParam elementalBondsMoveParam, ElementalBondsOperateResult elementalBondsOperateResult,
                                                       Random random, ElementalBondsGameData elementalBondsGameData, Set<ElementalBondsBlock> lastRoundDropSet, int round,
                                                       Set<ElementalBondsBlock> roundEliminateSet, ElementalBondsOperateRoundResult elementalBondsOperateRoundResult) {
        List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

        // 生成炸弹
        List<ElementalBondsBlock> logAddStepBlockList = new ArrayList<>();
        List<ElementalBondsBlock> newBombList = getCreateBombList(round, elementalBondsMoveParam, roundEliminateSet, lastRoundDropSet, random, logAddStepBlockList, elementalBondsGameData);
        for (ElementalBondsBlock bomb : newBombList) {
            blockList.get(bomb.getY()).set(bomb.getX(), bomb);
        }
        elementalBondsOperateRoundResult.setNewBombList(newBombList);

        // 设置加步数格子
        if (!logAddStepBlockList.isEmpty() && elementalBondsOperateResult.getBombAddStepStatus() == 0) {
            ElementalBondsOperateStageResult elementalBondsOperateStageResult = elementalBondsOperateRoundResult.getStageResultList().get(0);
            elementalBondsOperateStageResult.getAddStepBlockList().addAll(logAddStepBlockList);
            elementalBondsOperateResult.setBombAddStepStatus(1);
        }
        return newBombList;
    }

    /**
     * 获取生成的炸弹
     *
     * @param elementalBondsMoveParam 可能为null
     */
    public static List<ElementalBondsBlock> getCreateBombList(int round, ElementalBondsMoveParam elementalBondsMoveParam,
                                                              Set<ElementalBondsBlock> eliminateSet, Set<ElementalBondsBlock> dropSet, Random random,
                                                              List<ElementalBondsBlock> logAddStepBlockList, ElementalBondsGameData elementalBondsGameData) {
        List<ElementalBondsBlock> addBombList = new ArrayList<>();

        // 分组
        Map<Integer, List<List<ElementalBondsBlock>>> listListMap = ElementalBondsEliminateLogic.groupEliminateSet(eliminateSet);

        // 遍历生成炸弹
        for (List<List<ElementalBondsBlock>> listList : listListMap.values()) {
            for (int i = 0; i < listList.size(); i++) {
                List<ElementalBondsBlock> elementalBondsBlockList = listList.get(i);
                // 匹配形状
                ElementalBondsShapeMatchResult elementalBondsShapeMatchResult = ElementalBondsShapeLogic.matchShape(elementalBondsBlockList);
                if (elementalBondsShapeMatchResult != null) {
                    // 生成炸弹
                    ElementalBondsBlock bombBlock = createBombBlock(elementalBondsShapeMatchResult, round, elementalBondsMoveParam, dropSet, random, elementalBondsGameData);
                    // 配置控制规则开关
                    if (ElementalBondsParam.getInstance().getUseNewRule() == 0) {
                        // 剩余格子继续生成炸弹
                        elementalBondsBlockList.removeAll(elementalBondsShapeMatchResult.getElementalBondsBlockList());
                        if (!elementalBondsBlockList.isEmpty()) {
                            i--;
                        }
                    }
                    addBombList.add(bombBlock);
                    // 记录下增加步数的炸弹
                    if (elementalBondsShapeMatchResult.getElementalBondsBlockList().size() > logAddStepBlockList.size()) {
                        logAddStepBlockList.clear();
                        logAddStepBlockList.addAll(elementalBondsShapeMatchResult.getElementalBondsBlockList());
                    }
                }
            }
        }

        return addBombList;
    }

    /**
     * 生成炸弹格子
     *
     * @param elementalBondsMoveParam 可能为null
     */
    public static ElementalBondsBlock createBombBlock(ElementalBondsShapeMatchResult elementalBondsShapeMatchResult,
                                                      int round, ElementalBondsMoveParam elementalBondsMoveParam,
                                                      Set<ElementalBondsBlock> dropSet, Random random,
                                                      ElementalBondsGameData elementalBondsGameData) {
        // 【找生成炸弹的位置】
        ElementalBondsCalcBombPosResult elementalBondsCalcBombPosResult = calcCreateBombPos(elementalBondsShapeMatchResult.getElementalBondsBlockList(), round, elementalBondsMoveParam, dropSet);

        // 【计算炸弹类型】
        ElementalBondsBlockType bombType = ElementalBondsBlockType.NONE;
        ElementalBondsBlockType appointBombType = elementalBondsShapeMatchResult.getElementalBondsShapeConfig().getElementalBondsShapeType().getElementalBondsBlockType();

        if (appointBombType != ElementalBondsBlockType.NONE) { // 指定形状
            bombType = appointBombType;
        } else if (elementalBondsShapeMatchResult.getElementalBondsShapeConfig().getNeedCount() == 4) { // 单行4个：看交换方向，没有的就随机
            if (round == 1 && elementalBondsMoveParam != null && elementalBondsCalcBombPosResult.isContainsMoveBlock()) {
                bombType = elementalBondsMoveParam.getFromY() == elementalBondsMoveParam.getToY() ? ElementalBondsBlockType.LINE_BOMB : ElementalBondsBlockType.COLUMN_BOMB;
            } else {
                bombType = random.nextInt(1000) < 500 ? ElementalBondsBlockType.LINE_BOMB : ElementalBondsBlockType.COLUMN_BOMB;
            }
        }

        if (bombType == ElementalBondsBlockType.NONE) {
            bombType = ElementalBondsBlockType.NORMAL;
        }

        // 生成炸弹格子
        ElementalBondsBlock posBlock = elementalBondsCalcBombPosResult.getElementalBondsBlock();
        ElementalBondsBlock createBlock = new ElementalBondsBlock(posBlock.getX(), posBlock.getY(), posBlock.getColor());
        createBlock.setElementalBondsBlockType(bombType);
        ElementalBondsSceneLogic.scene_12_checkEffectChange(createBlock, elementalBondsGameData);

        return createBlock;
    }

    /**
     * 计算炸弹生成位置
     *
     * @param elementalBondsMoveParam 可能为null
     */
    private static ElementalBondsCalcBombPosResult calcCreateBombPos(List<ElementalBondsBlock> elementalBondsBlockList, int round,
                                                                     ElementalBondsMoveParam elementalBondsMoveParam, Set<ElementalBondsBlock> dropSet) {
        // 第一轮 && 移动 && 包含交换的格子
        boolean firstRound = round == 1;
        if (firstRound && elementalBondsMoveParam != null) {
            Optional<ElementalBondsBlock> elementalBondsBlockOptional = elementalBondsBlockList.stream()
                    .filter(elementalBondsBlock -> elementalBondsBlock.getX() == elementalBondsMoveParam.getToX()
                            && elementalBondsBlock.getY() == elementalBondsMoveParam.getToY())
                    .findAny();
            if (elementalBondsBlockOptional.isPresent()) {
                return new ElementalBondsCalcBombPosResult(elementalBondsBlockOptional.get(), true);
            }
            elementalBondsBlockOptional = elementalBondsBlockList.stream()
                    .filter(elementalBondsBlock -> elementalBondsBlock.getX() == elementalBondsMoveParam.getFromX()
                            && elementalBondsBlock.getY() == elementalBondsMoveParam.getFromY())
                    .findAny();
            if (elementalBondsBlockOptional.isPresent()) {
                return new ElementalBondsCalcBombPosResult(elementalBondsBlockOptional.get(), true);
            }
        }

        // 包含掉落格子（useBlock是小到大排序的）
        for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
            if (dropSet.contains(elementalBondsBlock)) {
                return new ElementalBondsCalcBombPosResult(elementalBondsBlock, false);
            }
        }

        return new ElementalBondsCalcBombPosResult(elementalBondsBlockList.get(0), false);
    }

}
